package mathutility;




/**
 * 数学計算ユーティリティー
 */
public class MathUtility
{
	/** 円周率 */
	public static final double PI = Math.PI;

	/**
	 * 絶対値.
	 */
	public static int ABS( int value )
	{
		return ( ( value < 0 ) ? -(value) : (value) );
	}
	public static long ABS( long value )
	{
		return ( ( value < 0 ) ? -(value) : (value) );
	}
	public static float ABS( float value )
	{
		return ( ( value < 0 ) ? -(value) : (value) );
	}
	public static double ABS( double value )
	{
		return ( ( value < 0 ) ? -(value) : (value) );
	}
	/**************/

	/**
	 * 小さい値を求める.
	 */
	public static int MIN( int value1, int value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	public static long MIN( long value1, long value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	public static double MIN( double value1, double value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	public static float MIN( float value1, float value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	/**************************/

	/**
	 * 大きい値を求める.
	 */
	public static int MAX( int value1, int value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	public static long MAX( long value1, long value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	public static double MAX( double value1, double value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	public static float MAX( float value1, float value2 )
	{
		return ( ( value1 > value2 ) ? ( value2 ) : ( value1 ) );
	}
	/*************************/

	/**
	 * 正なら１，負なら－１，ゼロなら０を返す．
	 */
	public static int ZSGN( int value )
	{
		return ( ( (value) < 0 ) ? -1 : (value) > 0 ? 1 : 0 );
	}
	public static int ZSGN( long value )
	{
		return ( ( (value) < 0 ) ? -1 : (value) > 0 ? 1 : 0 );
	}
	public static int ZSGN( float value )
	{
		return ( ( (value) < 0 ) ? -1 : (value) > 0 ? 1 : 0 );
	}
	public static int ZSGN( double value )
	{
		return ( ( (value) < 0 ) ? -1 : (value) > 0 ? 1 : 0 );
	}
	/*****************************/

	/**
	 * ａが正またはゼロなら１，負なら－１なら０を返す．
	 */
	public static int SGN( int value )
	{
		return ( ( (value) < 0 ) ? -1 : 1 );
	}
	public static int SGN( long value )
	{
		return ( ( (value) < 0 ) ? -1 : 1 );
	}
	public static int SGN( float value )
	{
		return ( ( (value) < 0 ) ? -1 : 1 );
	}
	public static int SGN( double value )
	{
		return ( ( (value) < 0 ) ? -1 : 1 );
	}
	/*****************************/

	/**
	 * ２乗値を返す.
	 */
	public static int SQR( int value )
	{
		return ( value * value );
	}
	public static long SQR( long value )
	{
		return ( value * value );
	}
	public static float SQR( float value )
	{
		return ( value * value );
	}
	public static double SQR( double value )
	{
		return ( value * value );
	}
	/******************************/


	/**
	 * 値をminからmaxの間に留める.
	 *
	 * @param value 値
	 * @param min   最小値
	 * @param max	最大値
	 * @return	保管した値
	 */
	public static int CLAMP( int value, int min, int max )
	{
		return MAX( min, MIN( value, max ) );
	}
	public static long CLAMP( long value, long min, long max )
	{
		return MAX( min, MIN( value, max ) );
	}
	public static float CLAMP( float value, float min, float max )
	{
		return MAX( min, MIN( value, max ) );
	}
	public static double CLAMP( double value, double min, double max )
	{
		return MAX( min, MIN( value, max ) );
	}


	/**
	 * 線形補間を行う.
	 *
	 * @param rate　補間の割合
	 * @param min	最小値
	 * @param max	最大値
	 * @return	補間した値
	 */
	public static float LERP( float rate, float min, float max )
	{
		return ( min + ( ( max - min ) * rate ) );
	}

	/**
	 * ２次補間を行う.
	 *
	 * @param rate 割合
	 * @param min　最小値
	 * @param mid　中間地
	 * @param max　最大値
	 * @return　補間した値
	 */
	public static float QUADRATIC( float rate, float min, float mid, float max )
	{
		return (min) * ( 1.0f - (rate) )
					 * ( 1.0f - (rate) )
					 + 2 * (mid) * (rate)
					 * ( 1.0f - (rate) )
					 + (max) * (rate) * (rate);
	}


	/**
	 * 整数型乱数の生成
	 *
	 * @param max 乱数の最大値
	 * @param min 乱数の最小値
	 * @return 整数型乱数
	 */
	public static int rand( int max, int min )
	{
		int value = (int)( ( Math.random() * ( max + 1 - min ) ) + min );

		return value;
	}

	/**
	 * 浮動小数点型乱数の生成
	 *
	 * @param max 乱数の最大値
	 * @param min 乱数の最小値
	 * @return 浮動小数点型乱数
	 */
	public static float rand( float max, float min )
	{
		float value = (float)( ( Math.random() * ( max + 1 - min ) ) + min );

		return value;
	}

	/**
	 * 平方根を求める
	 *
	 * @param value 値
	 * @return　平方根
	 */
	public static float sqrt( float value )
	{
		return (float)Math.sqrt( value );
	}

	/**
	 * ラジアンを求める．
	 *
	 * @param [in] deg  角度 ．
	 * @return   ラジアン．
	 */
	static float DegToRad( float angle )
	{
		return (float) ( (angle) * ( 1.0f / 180.0f * PI ) );
	}

	/**
	 * 角度を求める．
	 *
	 * @param [in] rad  ラジアン ．
	 * @return   角度．
	 */
	static float RadToDeg( float rad )
	{
		return (float) ( (rad) * (1.0f / PI * 180.0f ) );
	}

	/**
	 * 正規化した角度を求める．
	 *
	 * @param [in] rad  角度 ．
	 * @return   正規化した角度．
	 */
	static float DegreeNormalize( float rad )
	{
		return ( ( (rad) >= 0.0f ) ? ( ( rad % 360.0f ) )
			   : ( (  rad % 360.0f ) + 360.0f ) );
	}

	/**
	 * 正弦を求める
	 *
	 * @param angle　角度
	 * @return　正弦値
	 */
	public static float sin( float angle )
	{
		return (float) ( Math.sin( DegToRad( angle ) ) );
	}


	/**
	 * 余弦を求める
	 *
	 * @param angle　角度
	 * @return　余弦値
	 */
	public static float cos( float angle )
	{
		return (float)( Math.cos( DegToRad( angle ) ) );
	}

	/**
	 * 正接を求める
	 *
	 * @param angle　角度
	 * @return　正接値
	 */
	public static float tan( float angle )
	{
		return (float)( Math.tan( DegToRad( angle ) ) );
	}

	/**
	 * 逆正弦を求める．
	 *
	 * @param [in] deg  角度 ．
	 * @return   逆正弦．
	 */
	static float Asin( float deg )
	{
		return ( RadToDeg( (float) Math.asin( deg ) ) );
	}

	/**
	 * 逆余弦を求める．
	 *
	 * @param [in] deg  角度 ．
	 * @return   逆余弦．
	 */
	static float Acos( float deg )
	{
		return ( ( RadToDeg( (float) Math.acos( deg ) ) ) );
	}

	/**
	 * 逆正接を求める．
	 *
	 * @param [in] deg  角度 ．
	 * @return   逆正接．
	 */
	static float Atan( float deg1, float deg2 )
	{
		return ( ( DegreeNormalize( RadToDeg( (float) Math.atan2( deg1, deg2 ) ) ) ) );
	}
}